import QtQuick 1.1
import "."

Item{
    id: figure

    // interface towards tetris board
    property int boardWidth         // board size in pixels
    property int boardHeight
    property int boardSizeX: 30     // board size in figure components
    property int boardSizeY: 30

    property variant control
    property color bgrndColor: 'darkgreen'
    property int velocity: 50
    property int repeatRate: 500
    property variant figPattern: [  [0,0,0,0],
                                    [0,0,0,0],
                                    [1,2,3,4],
                                    [0,0,0,0]]

    // color names see http://www.w3.org/TR/SVG/types.html#ColorKeywords
    property variant colorDef:   [  "transparent",
                                    '#5BE61F',
                                    '#0278A5',
                                    '#FF8500',
                                    '#F0002B']
    //internal
    property int blockWidth: boardWidth / boardSizeX
    property int blockHeight: boardHeight / boardSizeY

    //data
    height: childrenRect.height
    width: childrenRect.width

    signal checkmove
    signal reachedBottom
    signal endTheGame

    Component.onCompleted:{
        setColorPattern();
        control.pressedChanged.connect(repeatCommand);
        figure.state = "falling";
    }

    onYChanged: {
        figure.checkmove();
    }

    onStateChanged: {
        if(figure.state !== "falling"){
            copyBlocks();
            if(Math.round(figure.y) === 0){
                figure.endTheGame();
            }else{
                figure.reachedBottom();
            }
            figure.destroy();
            scanlevel();
        }
    }

    function rotateFigure(){
        //NOTE: there is no use of transform.Rotate because there is no way to get element in device's coordinates
        // mapFromItem / mapToItem function result gets spoiled with transformation. So here is manual rotation
        figure.figPattern = rotate90().slice(0);
        setColorPattern();
    }

    function scanlevel(){
        var blockArr = new Array();
        for(var i = 0; i < figure.parent.children.length; i++){
            var obj = figure.parent.children[i];
            if(obj.objectName !== "frozenBlk"){
                continue;
            }
            blockArr.push(obj);
        }

        var sortfunction = function(a, b){
            //Compare "a" and "b" in some fashion, and return -1, 0, or 1
            // we want to return array sorted in descent order
            if(a.y < b.y) return 1
            else if(a.y === b.y) return 0;
            return -1
        }

        blockArr.sort(sortfunction);

        var startLevelIdx = 0;
        var level = blockArr[startLevelIdx].y;
        var grouppedArr = new Array();
        for(var j = 0, groupidx = 0; j < blockArr.length; j++){
            if(level !== blockArr[j].y){
                // level has changed
                level = blockArr[j].y;
                grouppedArr.push(blockArr.slice(startLevelIdx, j));
                startLevelIdx = j;
            }
        }
        grouppedArr.push(blockArr.slice(startLevelIdx));

        var moveBlocksFromIdx = -1;
        var multiple = 0;
        for(var k = 0; k < grouppedArr.length ; k++){
            if(grouppedArr[k].length >= figure.boardSizeX){
                // collapse the level and move next that that position
                while(grouppedArr[k].length > 0){
                    var block = grouppedArr[k].shift();
                    block.destroy();
                }
                if(moveBlocksFromIdx < 0){
                    moveBlocksFromIdx = k + 1;
                }
                multiple++;
            }
        }

        if(moveBlocksFromIdx > 0){
            for(var m = moveBlocksFromIdx; m < grouppedArr.length ; m++){
                for(var movingIdx = 0; movingIdx < grouppedArr[m].length; movingIdx++){
                    grouppedArr[m][movingIdx].y += figure.blockHeight * multiple;
                }
            }
        }
    }

    function rotate90(){
        var cnSize = figPattern[0].length;
        var dest = figPattern.slice(0);
        for (var j = 0; j < cnSize; ++j)
        {
            for (var i = 0; i < cnSize; ++i)
            {
                dest[j][ cnSize - 1 - i] = figPattern[i][j];
            }
        }
        return dest;
    }

    function setColorPattern(){
        var cnSize = figPattern[0].length;
        var row = 0;
        for(var i = 0; i < grid.children.length; i++) {
            var col = i % cnSize;
            var color = colorDef[figPattern[row][col]];
            if(typeof(color) !== "undefined"){
                grid.children[i].color = color;
                //NOTE: this is workaround for https://bugreports.qt-project.org/browse/QTBUG-21122
                grid.children[i].istransparent = (figPattern[row][col] === 0);
            }
            if(col === (cnSize - 1)){
                row++;
            }
        }
    }

    function copyBlocks(){
        for(var i = 0; i < grid.children.length ; i++) {
            var child = grid.children[i];
            if(child.istransparent){
                continue;
            }
            var obj = mapToItem(figure.parent, child.x, child.y);
            //normalize coord values
            var pointx = Math.round(obj.x / figure.blockWidth) * figure.blockWidth;
            var pointy = Math.round(obj.y / figure.blockHeight) * figure.blockHeight;
            Qt.createQmlObject(
                        'import QtQuick 1.0; ' +
                        'Rectangle {color: "' + ''+child.color + '"' +
                        '; objectName: "frozenBlk"' +
                        '; width: ' + child.width +
                        '; height: ' + child.height +
                        '; z: 1 ' +                    //send to top
                        '; x: ' + pointx +
                        '; y: ' + pointy + '}',figure.parent);
        }
    }

    function updateposition(mousevent){
        if(figure.state === "falling"){
            var figsize = pureWidth();
            var offset = figure.x;
            offset += (control.mouseX > figure.boardWidth / 2) ? figure.blockWidth : -figure.blockWidth;
            if(offset < -figsize.x){
                offset = -figsize.x;
            }else if( offset + figsize.y + figure.blockWidth - figure.boardWidth > 0){
                offset = figure.boardWidth - figsize.y - figure.blockWidth;
            }
            figure.x = offset;
        }
    }

    function pureWidth(){
        var minx = figure.width;
        var maxx = 0;
        for(var i = 0; i < grid.children.length; i++){
            var obj = grid.children[i];
            if(obj.istransparent){
                continue;
            }
            minx = Math.min(minx, obj.x);
            maxx = Math.max(maxx, obj.x);
        }
        return Qt.point(minx, maxx);
    }

    function repeatCommand(){
        cmdRepeatTimer.running = figure.control.pressed;
    }

    function repeatFromBlock(mouse){
        cmdRepeatTimer.running = mouse.pressed;
    }

    Timer {
        id: cmdRepeatTimer
        interval: figure.repeatRate; running: false; repeat: true
        onTriggered: updateposition(null)
    }

    Grid {
        id: grid
        columns: figPattern.length
        //NOTE: dynamic creation does not work here because
        // the parent is being created dynamically
        Block{figure: figure}
        Block{figure: figure}
        Block{figure: figure}
        Block{figure: figure}
        Block{figure: figure}
        Block{figure: figure}
        Block{figure: figure}
        Block{figure: figure}
        Block{figure: figure}
        Block{figure: figure}
        Block{figure: figure}
        Block{figure: figure}
        Block{figure: figure}
        Block{figure: figure}
        Block{figure: figure}
        Block{figure: figure}
    }

    Behavior on x {
        SmoothedAnimation{
            velocity: figure.velocity
        }
    }

    Behavior on y {
        SmoothedAnimation{velocity: figure.velocity
        }
    }

    states:[
        State {
            name: "falling"
            PropertyChanges{target: figure; explicit: true; y: figure.boardHeight}
        },
        State {
            name: "stop"
            PropertyChanges{target: figure; y:y}
        }
    ]
}


